<!--
  智慧小区管理系统 - 搜索表单组件
  @author Wu.Liang
  @date 2024-12-21
  @description 使用 Vue 3.4.21 defineModel 新特性的示例组件
-->
<template>
    <div class="search-form">
        <el-form
            ref="formRef"
            :model="formData"
            :inline="inline"
            :label-width="labelWidth"
            class="search-form__form"
        >
            <el-form-item
                v-for="field in fields"
                :key="field.prop"
                :label="field.label"
                :prop="field.prop"
                :class="field.class"
            >
                <!-- 输入框 -->
                <el-input
                    v-if="field.type === 'input'"
                    v-model="formData[field.prop]"
                    :placeholder="field.placeholder"
                    :clearable="field.clearable !== false"
                    :size="size"
                    @input="handleInput(field.prop, $event)"
                />

                <!-- 选择器 -->
                <el-select
                    v-else-if="field.type === 'select'"
                    v-model="formData[field.prop]"
                    :placeholder="field.placeholder"
                    :clearable="field.clearable !== false"
                    :size="size"
                    @change="handleChange(field.prop, $event)"
                >
                    <el-option
                        v-for="option in field.options"
                        :key="option.value"
                        :label="option.label"
                        :value="option.value"
                    />
                </el-select>

                <!-- 日期选择器 -->
                <el-date-picker
                    v-else-if="field.type === 'date'"
                    v-model="formData[field.prop]"
                    :type="field.dateType || 'date'"
                    :placeholder="field.placeholder"
                    :format="field.format"
                    :value-format="field.valueFormat"
                    :size="size"
                    @change="handleChange(field.prop, $event)"
                />

                <!-- 日期范围选择器 -->
                <el-date-picker
                    v-else-if="field.type === 'daterange'"
                    v-model="formData[field.prop]"
                    type="daterange"
                    :start-placeholder="field.startPlaceholder || '开始日期'"
                    :end-placeholder="field.endPlaceholder || '结束日期'"
                    :format="field.format"
                    :value-format="field.valueFormat"
                    :size="size"
                    @change="handleChange(field.prop, $event)"
                />
            </el-form-item>

            <!-- 操作按钮 -->
            <el-form-item class="search-form__actions">
                <el-button
                    type="primary"
                    :icon="Search"
                    :size="size"
                    @click="handleSearch"
                >
                    搜索
                </el-button>
                <el-button
                    :icon="Refresh"
                    :size="size"
                    @click="handleReset"
                >
                    重置
                </el-button>
                <slot name="actions" :form-data="formData" />
            </el-form-item>
        </el-form>
    </div>
</template>

<script setup lang="ts">
/**
 * 搜索表单组件
 * 使用 Vue 3.4.21 defineModel 新特性
 */
import { ref, reactive, watch, computed } from 'vue'
import { ElForm } from 'element-plus'
import { Search, Refresh } from '@element-plus/icons-vue'

// 使用 defineModel 双向绑定（Vue 3.4.21 新特性）
const modelValue = defineModel<Record<string, any>>('modelValue', {
    default: () => ({})
})

// 表单字段配置类型
interface FormField {
    prop: string
    label: string
    type: 'input' | 'select' | 'date' | 'daterange'
    placeholder?: string
    clearable?: boolean
    class?: string
    // 选择器配置
    options?: Array<{ label: string; value: any }>
    // 日期配置
    dateType?: string
    format?: string
    valueFormat?: string
    startPlaceholder?: string
    endPlaceholder?: string
}

// 组件属性
interface Props {
    fields: FormField[]
    inline?: boolean
    labelWidth?: string | number
    size?: 'large' | 'default' | 'small'
}

// 使用 withDefaults 设置默认值
const props = withDefaults(defineProps<Props>(), {
    inline: true,
    labelWidth: 'auto',
    size: 'default'
})

// 组件事件
interface Emits {
    search: [data: Record<string, any>]
    reset: []
    change: [prop: string, value: any]
}

const emit = defineEmits<Emits>()

// 表单引用
const formRef = ref<InstanceType<typeof ElForm>>()

// 表单数据（响应式）
const formData = reactive<Record<string, any>>({})

// 初始化表单数据
const initFormData = () => {
    props.fields.forEach(field => {
        if (!(field.prop in formData)) {
            formData[field.prop] = field.type === 'daterange' ? [] : ''
        }
    })
}

// 监听 modelValue 变化
watch(
    () => modelValue.value,
    (newVal) => {
        Object.assign(formData, newVal)
    },
    { immediate: true, deep: true }
)

// 监听 formData 变化，同步到 modelValue
watch(
    formData,
    (newVal) => {
        modelValue.value = { ...newVal }
    },
    { deep: true }
)

// 计算属性：是否有数据
const hasData = computed(() => {
    return Object.values(formData).some(value => {
        if (Array.isArray(value)) {
            return value.length > 0
        }
        return value !== '' && value !== null && value !== undefined
    })
})

// 处理输入事件
const handleInput = (prop: string, value: any) => {
    formData[prop] = value
    emit('change', prop, value)
}

// 处理变化事件
const handleChange = (prop: string, value: any) => {
    formData[prop] = value
    emit('change', prop, value)
}

// 处理搜索
const handleSearch = async() => {
    if (!formRef.value) return

    try {
        const valid = await formRef.value.validate()
        if (valid) {
            emit('search', { ...formData })
        }
    } catch (error) {
        console.warn('表单验证失败:', error)
    }
}

// 处理重置
const handleReset = () => {
    if (!formRef.value) return

    formRef.value.resetFields()

    // 重置表单数据
    props.fields.forEach(field => {
        formData[field.prop] = field.type === 'daterange' ? [] : ''
    })

    emit('reset')
}

// 暴露方法给父组件
defineExpose({
    validate: () => formRef.value?.validate(),
    resetFields: () => formRef.value?.resetFields(),
    clearValidate: () => formRef.value?.clearValidate(),
    formData,
    hasData
})

// 初始化
initFormData()
</script>

<style lang="scss" scoped>
.search-form {
    background: #fff;
    border-radius: 6px;
    padding: 16px;
    margin-bottom: 16px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);

    &__form {
        .el-form-item {
            margin-bottom: 16px;
            margin-right: 16px;

            &:last-child {
                margin-right: 0;
            }
        }
    }

    &__actions {
        .el-button + .el-button {
            margin-left: 8px;
        }
    }

    // 响应式布局
    @media (max-width: 768px) {
        &__form {
            :deep(.el-form-item) {
                display: block;
                margin-right: 0;

                .el-form-item__content {
                    margin-left: 0 !important;
                }
            }
        }
    }
}

// 深度选择器适配新版本
:deep(.el-form-item__label) {
    color: #606266;
    font-weight: 500;
}

:deep(.el-input__wrapper) {
    border-radius: 4px;
}

:deep(.el-select) {
    width: 100%;
}
</style>
